package wxpay

import (
	"crypto/aes"
	"crypto/cipher"
	"encoding/base64"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"log"
	"server/global"

	"github.com/gin-gonic/gin"
)

// 1. 定义回调数据结构（映射微信支付回调JSON）
// 外层回调结构
type WxCallback struct {
	ID           string            `json:"id"`            // 通知ID
	CreateTime   string            `json:"create_time"`   // 通知创建时间
	ResourceType string            `json:"resource_type"` // 通知数据类型
	EventType    string            `json:"event_type"`    // 通知类型
	Summary      string            `json:"summary"`       // 回调摘要
	Resource     EncryptedResource `json:"resource"`      // 加密的业务数据
}

// 加密资源结构（包含解密所需信息）
type EncryptedResource struct {
	OriginalType   string `json:"original_type"`   // 原始数据类型
	Algorithm      string `json:"algorithm"`       // 加密算法（固定为AEAD_AES_256_GCM）
	Ciphertext     string `json:"ciphertext"`      // 加密的业务数据（base64编码）
	AssociatedData string `json:"associated_data"` // 关联数据
	Nonce          string `json:"nonce"`           // 随机串（解密用）
}

// 解密后的业务数据结构（商家转账结果）
type TransferData struct {
	OutBillNo      string `json:"out_bill_no"`      // 商户单号
	TransferBillNo string `json:"transfer_bill_no"` // 微信转账单号
	State          string `json:"state"`            // 单据状态（SUCCESS/FAIL等）
	MchID          string `json:"mch_id"`           // 商户号
	TransferAmount int    `json:"transfer_amount"`  // 转账金额（分）
	OpenID         string `json:"openid"`           // 收款用户OpenID
	FailReason     string `json:"fail_reason"`      // 失败原因（可选）
	CreateTime     string `json:"create_time"`      // 单据创建时间
	UpdateTime     string `json:"update_time"`      // 状态更新时间
}

// 2. 核心解密函数（AES-256-GCM解密）
// 参数：APIv3密钥（32字节）、随机串nonce、关联数据associatedData、加密数据ciphertext
func decrypt(apiV3Key, nonce, associatedData, ciphertext string) (string, error) {
	// 校验APIv3密钥长度（必须32字节）
	key := []byte(apiV3Key)
	if len(key) != 32 {
		return "", errors.New("APIv3密钥必须为32字节")
	}

	// 解码加密数据（微信返回的ciphertext是base64编码）
	cipherBytes, err := base64.StdEncoding.DecodeString(ciphertext)
	if err != nil {
		return "", fmt.Errorf("ciphertext base64解码失败: %w", err)
	}

	// 初始化AES加密器
	block, err := aes.NewCipher(key)
	if err != nil {
		return "", fmt.Errorf("创建AES加密器失败: %w", err)
	}

	// 初始化GCM模式（AES-256-GCM）
	gcm, err := cipher.NewGCM(block)
	if err != nil {
		return "", fmt.Errorf("创建GCM模式失败: %w", err)
	}

	// 解密：GCM会自动从cipherBytes末尾提取16字节的标签（tag）
	// 参数说明：
	// - nil：输出缓冲区（传nil自动分配）
	// - nonce：随机串（必须与加密时一致）
	// - cipherBytes：加密数据（包含密文+标签）
	// - associatedData：关联数据（可选，微信回调中为"mch_payment"）
	plaintext, err := gcm.Open(nil, []byte(nonce), cipherBytes, []byte(associatedData))
	if err != nil {
		return "", fmt.Errorf("解密失败: %w", err)
	}

	return string(plaintext), nil
}

func Notice(c *gin.Context) (TransferData, error) {
	// 步骤1：接收并读取原始请求体（微信回调为JSON格式）
	rawBody, err := io.ReadAll(c.Request.Body)
	if err != nil {
		log.Printf("读取请求体失败: %v", err)
		return TransferData{}, err
	}

	// 步骤2：解析原始JSON到回调结构体
	var callback WxCallback
	if err := json.Unmarshal(rawBody, &callback); err != nil {
		log.Printf("解析回调数据失败: %v, 原始数据: %s", err, rawBody)
		return TransferData{}, err
	}

	// 步骤3：验证加密算法（目前仅支持AEAD_AES_256_GCM）
	if callback.Resource.Algorithm != "AEAD_AES_256_GCM" {
		log.Printf("不支持的加密算法: %s", callback.Resource.Algorithm)
		return TransferData{}, err
	}

	// 步骤4：解密业务数据（使用APIv3密钥）
	// 注意：APIv3密钥需从商户平台获取（32位随机字符串），勿硬编码！
	decryptedStr, err := decrypt(
		global.GL_CONFIG.WxJsApi.MchAPIv3Key,
		callback.Resource.Nonce,
		callback.Resource.AssociatedData,
		callback.Resource.Ciphertext,
	)
	if err != nil {
		log.Printf("解密失败: %v", err)
		return TransferData{}, err
	}

	// 步骤5：解析解密后的业务数据
	var transferData TransferData
	if err := json.Unmarshal([]byte(decryptedStr), &transferData); err != nil {
		log.Printf("解析业务数据失败: %v, 解密后数据: %s", err, decryptedStr)
		//c.JSON(http.StatusInternalServerError, gin.H{"code": "FAIL", "message": "解析业务数据失败"})
		return TransferData{}, err
	}

	// 步骤6：处理业务数据（此处仅打印，实际需根据状态更新订单等）
	log.Printf("解密成功，业务数据: %+v", transferData)
	return transferData, err

}
